﻿using System;
using System.ComponentModel;


namespace WCFMINERP.ComControls
{
	using System.Reflection;

	public class DisplayItem : IConvertible, ICloneable, INotifyPropertyChanged {
		private readonly Func<DisplayItem, object> _convertAction;
		private readonly Action<object, string> _pAction;
		private readonly Action<object, object> _pDV1Action;
		private string _displayField;
		private object _displayValue1;
		private string _mnemonicCode;
		private string _mnemonicCode1;
		private object _value;
		private string _displayField2;

		

		public DisplayItem(object value, string display) {
			Value = value;
			DisplayField = display;
		}
		public DisplayItem(object value, string display, Action<object, string> pAction, Func<DisplayItem, object> convert = null,Action<object,object> displayValue1SetAction=null ) {
			Value = value;
			DisplayField = display;
			_pAction = pAction;
			_convertAction = convert;
			_pDV1Action=displayValue1SetAction;            
		    _mnemonicCode = MnemonicCode.chinesecap(DisplayField);
            _mnemonicCode1 = MnemonicCode.chinesecap(DisplayField).ToUpper();
		}
		public DisplayItem(object value, string displayField, Action<object, string> pAction) {
			Value = value;
			INotifyPropertyChanged d = value as INotifyPropertyChanged;
			object data;
			if (d != null) {
				d.PropertyChanged += (sender, args) => {
					if (args.PropertyName == displayField) {
						data = GetFieldValue(value, displayField);
						if (data != null) {
							DisplayField = data.ToString();
						}
					}
				};
			}
			data = GetFieldValue(value, displayField);
			if (data != null) {
				DisplayField = data.ToString();
			}
		}
		private static object GetFieldValue(object obj, string d) {
			PropertyInfo t = obj.GetType().GetProperty(d);
			object data = t.GetValue(obj, null);
			return data;
		}
		public DisplayItem() {
		}
		public virtual object Value {
			get { return _value; }
			set {
				_value = value;
				OnPropertyChanged("Value");
			}
		}
		public string DisplayField {
			get { return _displayField; }
			set {
				_displayField = value;
				if (_pAction != null) {
					_pAction(Value, value);
				}
				//_mnemonicCode = ConvertEx.GetFirstSpell(DisplayField);
				OnPropertyChanged("DisplayField");
				OnPropertyChanged("MnemonicCode");
			}
		}
		public string DisplayField2	 {
			get { return _displayField2; }
			set { _displayField2 = value; }
		}
		public object DisplayValue1 {
			get { return _displayValue1; }
			set {
				_displayValue1 = value;
				if (_pDV1Action != null) {
					_pDV1Action(DisplayValue1, value);}
				OnPropertyChanged("DisplayValue1");
				OnPropertyChanged("MnemonicCode1");
			}
		}	

		#region Implementation of IConvertible

		public TypeCode GetTypeCode() {
			return Convert.GetTypeCode(Value);
		}
		public bool ToBoolean(IFormatProvider provider) {
			return Convert.ToBoolean(Value, provider);
		}
		public char ToChar(IFormatProvider provider) {
			return Convert.ToChar(Value, provider);
		}
		public sbyte ToSByte(IFormatProvider provider) {
			return Convert.ToSByte(Value, provider);
		}
		public byte ToByte(IFormatProvider provider) {
			return Convert.ToByte(Value, provider);
		}
		public short ToInt16(IFormatProvider provider) {
			return Convert.ToInt16(Value, provider);
		}
		public ushort ToUInt16(IFormatProvider provider) {
			return Convert.ToUInt16(Value, provider);
		}
		public int ToInt32(IFormatProvider provider) {
			return Convert.ToInt32(Value);
		}
		public uint ToUInt32(IFormatProvider provider) {
			return Convert.ToUInt32(Value, provider);
		}
		public long ToInt64(IFormatProvider provider) {
			return Convert.ToInt64(Value, provider);
		}
		public ulong ToUInt64(IFormatProvider provider) {
			return Convert.ToUInt64(Value, provider);
		}
		public float ToSingle(IFormatProvider provider) {
			return Convert.ToSingle(Value, provider);
		}
		public double ToDouble(IFormatProvider provider) {
			return Convert.ToDouble(Value, provider);
		}
		public decimal ToDecimal(IFormatProvider provider) {
			return Convert.ToDecimal(Value, provider);
		}
		public DateTime ToDateTime(IFormatProvider provider) {
			return Convert.ToDateTime(Value, provider);
		}
		public string ToString(IFormatProvider provider) {
			return DisplayField;
		}
		public object ToType(Type conversionType, IFormatProvider provider) {
			if (_convertAction != null) {
				return _convertAction(this);
			}
			try {
				return Convert.ChangeType(Value, conversionType, provider);
			}
			catch (Exception) {
				return null;
			}
		}

		#endregion

		public object Clone() {
			DisplayItem clone = new DisplayItem();
			clone.Value = Value;
			clone.DisplayField = DisplayField;
			return clone;
		}
		public event PropertyChangedEventHandler PropertyChanged;
		public override int GetHashCode() {
			return Value != null ? Value.GetHashCode() : base.GetHashCode();
		}
		public override string ToString() {
			return DisplayField;
		}
		public void Recover(DisplayItem clone) {
			Value = clone.Value;
			DisplayField = clone.DisplayField;
		}
		// [NotifyPropertyChangedInvocator]
		protected virtual void OnPropertyChanged(string propertyName) {
			PropertyChangedEventHandler handler = PropertyChanged;
			if (handler != null) {
                handler(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
			}
		}
	}
}
